//
// Created by JZYFC on 2021/11/14.
//

#include "WndUtil.h"
#include "AddWnd.h"
#include "FontUtil.h"
#include "NoteWnd.h"
#include "../note_by_ps/addnew.h"
#include "../zm/del_and_mod.h"

#ifdef _UNICODE
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
#endif

#define ID_TEST_BTN 0x00

#define ID_ADD_WEEK_BTN 0x01

#define ID_MODIFY_WEEK_BTN 0x02

#define ID_MODIFY_DAY_BTN 0x03

#define ID_DELETE_WEEK_BTN 0x04

#define ID_DELETE_DAY_BTN 0x05

#define ID_ADD_DAY_BTN 0x06

#define ID_NOTE_BTN 0x09

#define ID_WEEK_LB 0x10

#define ID_DAY_LB 0x11

#define MAIN_WIDTH 720
#define MAIN_HEIGHT 450

void register_add_window(HWND hWnd);
void register_note_window(HWND hWnd);

void callRePaint(HWND hWnd, RECT *disp, TEXTMETRIC text_metric);

static list_head weekHead;
static list_head dayHead;
static bool is_update = false;

// TODO: TESTDATA
day_data current_data = {
        0, {2021, 11, 11, 11, 11},
        {2021, 11, 11, 11, 13},
        L"ABCDEF G\r\n你好换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行"
};

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    HDC hdc;
    static PAINTSTRUCT ps;

    static RECT week_rect;
    static RECT day_rect;
    static RECT sign;
    static RECT disp;

    static TEXTMETRIC text_metric;
    static HWND week_edit;
    static HWND day_edit;

    const int week_left = 232;
    const int week_top = 3;
    const int week_width = 236;
    const int week_height = 200;

    const int day_left = week_left + week_width + 1;
    const int day_width = 236;

    static HFONT font;

    list_head current;
    static int currentListBox;

    WCHAR initBuf[100];

    switch (msg) {
        case WM_CREATE:
            font = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
            // Add buttons
//            HWND hWndTestBtn = CreateWindowEx(
//                    WS_EX_LEFT,
//                    L"Button",
//                    L"Test",
//                    WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
//                    24,
//                    281,
//                    144,
//                    24,
//                    hWnd,
//                    (HMENU) ID_TEST_BTN, // 按钮ID
//                    (HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
//                    NULL
//            );

            HWND hWndAddWeekBtn = CreateWindowEx(
                    WS_EX_LEFT,
                    L"Button",
                    L"添加周计划",
                    WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
                    24,
                    321,
                    70,
                    24,
                    hWnd,
                    (HMENU) ID_ADD_WEEK_BTN,
                    (HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
                    NULL
            );
            HWND hWndAddDayBtn = CreateWindowEx(
                    WS_EX_LEFT,
                    L"Button",
                    L"添加日计划",
                    WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
                    98,
                    321,
                    70,
                    24,
                    hWnd,
                    (HMENU) ID_ADD_DAY_BTN,
                    (HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
                    NULL
            );

            HWND hWndModifWeekBtn = CreateWindowEx(
                    WS_EX_LEFT,
                    L"Button",
                    L"修改周计划",
                    WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
                    24,
                    361,
                    70,
                    24,
                    hWnd,
                    (HMENU) ID_MODIFY_WEEK_BTN,
                    (HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
                    NULL
            );
            HWND hWndModifyDayBtn = CreateWindowEx(
                    WS_EX_LEFT,
                    L"Button",
                    L"修改日计划",
                    WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
                    98,
                    361,
                    70,
                    24,
                    hWnd,
                    (HMENU) ID_MODIFY_DAY_BTN,
                    (HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
                    NULL
            );
            HWND hWndDeleteWeekBtn = CreateWindowEx(
                    WS_EX_LEFT,
                    L"Button",
                    L"删除周计划",
                    WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
                    24,
                    401,
                    70,
                    24,
                    hWnd,
                    (HMENU) ID_DELETE_WEEK_BTN,
                    (HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
                    NULL
            );
            HWND hWndDeleteDayBtn = CreateWindowEx(
                    WS_EX_LEFT,
                    L"Button",
                    L"删除日计划",
                    WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
                    98,
                    401,
                    70,
                    24,
                    hWnd,
                    (HMENU) ID_DELETE_DAY_BTN,
                    (HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
                    NULL
            );
            HWND hWndNoteBtn = CreateWindowEx(
                    WS_EX_LEFT,
                    L"Button",
                    L"打开笔记",
                    WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
                    24,
                    281,
                    144,
                    24,
                    hWnd,
                    (HMENU) ID_NOTE_BTN,
                    (HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
                    NULL
            );

            hdc = GetDC(hWnd);

            SelectObject(hdc, font);

            register_add_window(hWnd);
            register_note_window(hWnd);
            GetTextMetrics(hdc, &text_metric);

            // 周计划显示框
            week_edit = CreateWindowEx(
                    0, L"ListBox",
                    NULL,
                    WS_CHILD | WS_VISIBLE | LBS_STANDARD ^ LBS_SORT,
                    week_left + 1,
                    week_top + text_metric.tmHeight + 6,
                    week_width - 2,
                    week_height - 2,
                    hWnd,
                    (HMENU) ID_WEEK_LB,
                    (HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
                    NULL
            );

            // 日计划显示框
            day_edit = CreateWindowEx(
                    0, L"ListBox",
                    NULL,
                    WS_CHILD | WS_VISIBLE | LBS_STANDARD ^ LBS_SORT,
                    day_left + 1,
                    week_top + text_metric.tmHeight + 6,
                    day_width - 2,
                    week_height - 2,
                    hWnd,
                    (HMENU) ID_DAY_LB,
                    (HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
                    NULL
            );

            ReleaseDC(hWnd, hdc);
            EnumChildWindows(hWnd, EnumChildWndSetFont, (LPARAM) font);

            currentListBox = 0;

            current = weekHead->next;
            while (current != NULL) {
                swprintf(initBuf, 99, L"%s", current->data.todo);
                int pos = (int) SendMessage(week_edit, LB_ADDSTRING, 0, (LPARAM) initBuf);
                current = current->next;
            }
            current = dayHead->next;
            while (current != NULL) {
                swprintf(initBuf, 99, L"%s", current->data.todo);
                int pos = (int) SendMessage(day_edit, LB_ADDSTRING, 0, (LPARAM) initBuf);
                current = current->next;
            }
            current = weekHead->next;
            current_data = current->data;
            return 0;
        case WM_PAINT:

            hdc = BeginPaint(hWnd, &ps);
            //GetClientRect(hWnd, &week_rect);
            SelectObject(hdc, font);
            GetTextMetrics(hdc, &text_metric);

            // 周计划
            week_rect.left = week_left;
            week_rect.top = week_top;
            week_rect.right = week_left + week_width;
            week_rect.bottom = 24; // 文本
            DrawText(hdc, L"周计划", -1, &week_rect, DT_LEFT | DT_VCENTER);

            // 日计划
            day_rect.left = day_left;
            day_rect.top = week_rect.top;
            day_rect.right = day_left + day_width;
            day_rect.bottom = week_rect.bottom; // 文本
            DrawText(hdc, L"日计划", -1, &day_rect, DT_LEFT | DT_VCENTER);

            // 签名
            sign.left = 24;
            sign.top = 25;
            sign.right = MAIN_WIDTH - 552;
            sign.bottom = MAIN_HEIGHT - 193;
            Rectangle(hdc, sign.left, sign.top, sign.right, sign.bottom);
            sign.left += 10;
            DrawText(hdc, L"个性签名", -1, &sign, DT_LEFT | DT_VCENTER);
            sign.top += text_metric.tmHeight + 6;
            sign.bottom += text_metric.tmHeight + 6;

            // 信息显示区
            disp.left = 273;
            disp.top = 256;
            disp.right = MAIN_WIDTH - 16;
            disp.bottom = MAIN_HEIGHT - 25;
            Rectangle(hdc, disp.left, disp.top, disp.right, disp.bottom);
            disp.left += 2;
            disp.top += 2;
            disp.right -= 2;
            disp.bottom -= 2;

            WCHAR buf[30];
            switch (currentListBox) {
                case 0:
                    wcscpy(buf, L"当前选择: 周计划");
                    break;
                case 1:
                    wcscpy(buf, L"当前选择: 日计划");
                    break;
            }
            disp.top -= text_metric.tmHeight + 6;
            DrawText(hdc, buf, -1, &disp, DT_LEFT | DT_TOP);
            disp.top += text_metric.tmHeight + 6;
            swprintf(buf, 29, L"编号: %d", current_data.number);
            DrawText(hdc, buf, -1, &disp, DT_LEFT | DT_TOP);
            disp.top += text_metric.tmHeight + 6;
            swprintf(buf, 29, L"开始时间: %d年%d月%d日 %d:%d",
                     current_data.start_date.year, current_data.start_date.month, current_data.start_date.day,
                     current_data.start_date.hour, current_data.start_date.minute);
            DrawText(hdc, buf, -1, &disp, DT_LEFT | DT_TOP);
            disp.top += text_metric.tmHeight + 6;
            swprintf(buf, 29, L"截止时间: %d年%d月%d日 %d:%d",
                     current_data.due_date.year, current_data.due_date.month, current_data.due_date.day,
                     current_data.due_date.hour, current_data.due_date.minute);
            DrawText(hdc, buf, -1, &disp, DT_LEFT | DT_TOP);
            disp.top += text_metric.tmHeight + 6;
            DrawText(hdc, L"计划内容: ", -1, &disp, DT_LEFT | DT_TOP | DT_EDITCONTROL | DT_WORDBREAK);
            disp.top += text_metric.tmHeight + 6;
            DrawText(hdc, current_data.todo, -1, &disp, DT_LEFT | DT_TOP | DT_EDITCONTROL | DT_WORDBREAK);


            EndPaint(hWnd, &ps);
            if (is_update) {
                SendMessage(week_edit, LB_RESETCONTENT, 0, 0);
                SendMessage(day_edit, LB_RESETCONTENT, 0, 0);
                current = weekHead->next;
                while (current != NULL) {
                    swprintf(initBuf, 99, L"%s", current->data.todo);
                    int pos = (int) SendMessage(week_edit, LB_ADDSTRING, 0, (LPARAM) initBuf);
                    current = current->next;
                }
                current = dayHead->next;
                while (current != NULL) {
                    swprintf(initBuf, 99, L"%s", current->data.todo);
                    int pos = (int) SendMessage(day_edit, LB_ADDSTRING, 0, (LPARAM) initBuf);
                    current = current->next;
                }
                is_update = false;
            }
            return 0;
        case WM_COMMAND:
            switch (LOWORD(wParam)) {
                case ID_TEST_BTN:
                    RECT tmp;
                    GetClientRect(hWnd, &tmp);
                    WCHAR wstr[100];
                    swprintf(wstr, 99, L"left:%d\ntop:%d\nright:%d\nbottom:%d\ntext height:%d", tmp.left, tmp.top,
                             tmp.right,
                             tmp.bottom, text_metric.tmHeight);
                    MessageBox(hWnd, wstr, L"Button clicked", MB_OK);
                    break;
                case ID_ADD_WEEK_BTN:
                    // 添加周计划
                    open_add_window(hWnd, false, weekHead);
                    get_data(&current_data);
                    addnew(weekHead, current_data);
                    is_update = true;
                    callRePaint(hWnd, &disp, text_metric);
                    break;
                case ID_ADD_DAY_BTN:
                    // 添加日计划
                    open_add_window(hWnd, false, dayHead);
                    get_data(&current_data);
                    addnew(dayHead, current_data);
                    is_update = true;
                    callRePaint(hWnd, &disp, text_metric);
                    break;
                case ID_MODIFY_WEEK_BTN:
                    put_data(current_data);
                    open_add_window(hWnd, true, weekHead);
                    get_data(&current_data);
                    modifyNode(weekHead, current_data);
                    is_update = true;
                    callRePaint(hWnd, &disp, text_metric);
                    break;
                case ID_MODIFY_DAY_BTN:
                    // 修改
                    put_data(current_data);
                    open_add_window(hWnd, true, dayHead);
                    get_data(&current_data);
                    modifyNode(dayHead, current_data);
                    is_update = true;
                    callRePaint(hWnd, &disp, text_metric);
                    break;
                case ID_DELETE_WEEK_BTN:
                    deleteNode(weekHead, current_data);
                    is_update = true;
                    callRePaint(hWnd, &disp, text_metric);
                    break;
                case ID_DELETE_DAY_BTN:
                    deleteNode(dayHead, current_data);
                    is_update = true;
                    callRePaint(hWnd, &disp, text_metric);
                    break;
                case ID_NOTE_BTN:;
//                    open_note_window(hWnd);
                    FILE *file = NULL;
                    file = fopen("note.exe", "r");
                    if (file == NULL)
                        MessageBox(hWnd, L"笔记模块不存在", L"错误", MB_OK);
                    else system("start cmd /k note.exe");
                    break;
                case ID_WEEK_LB:
                    switch (HIWORD(wParam)) {
                        case LBN_SELCHANGE:;
                            int i = (int) SendMessage(week_edit, LB_GETCURSEL, 0, 0);
                            if (i < 0) return 0;
                            current = weekHead->next;
                            while (i--) {
                                current = current->next;
                            }
                            current_data = current->data;
                            currentListBox = 0;
                            is_update = false;
                            callRePaint(hWnd, &disp, text_metric);
                            break;
                    }
                    break;
                case ID_DAY_LB:
                    switch (HIWORD(wParam)) {
                        case LBN_SELCHANGE:;
                            int i = (int) SendMessage(day_edit, LB_GETCURSEL, 0, 0);
                            if (i < 0) return 0;
                            current = dayHead->next;
                            while (i--) {
                                current = current->next;
                            }
                            current_data = current->data;
                            currentListBox = 1;
                            is_update = false;
                            callRePaint(hWnd, &disp, text_metric);
                            break;
                    }
                    break;
            }
            return 0;
//        case WM_SETFONT:
//            EnumChildWindows()
//            break;
        case WM_CLOSE:
            DestroyWindow(hWnd);
            wprintf(L"Window closed\n");
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            wprintf(L"Window destroyed\n");
            break;
        default:
            return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    return 0;
}

void callRePaint(HWND hWnd, RECT *disp, TEXTMETRIC text_metric) {
    (*disp).left = 273;
    (*disp).top = 256 - text_metric.tmHeight - 6;
    (*disp).right = MAIN_WIDTH - 16;
    (*disp).bottom = MAIN_HEIGHT - 25;
    InvalidateRect(hWnd, disp, true);
    UpdateWindow(hWnd);
}


bool create_and_show_main_window(HWND hParent, list_head week_head, list_head day_head) {

    static bool isRegistered = false;

    weekHead = week_head;
    dayHead = day_head;

    int x = 100;
    int y = 100;
    WNDCLASSEX wc;
    int width = 720 + 16;
    int height = 450 + 39;
    LPCWSTR lpClassName = L"mWndClass";
    LPCWSTR lpWindowName = L"拯救DDL";

    // Set class info
    const HINSTANCE hInstance = NULL;
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0x00;
    wc.lpfnWndProc = MainWndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = lpClassName;
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    // Register window class
    if (!isRegistered && !RegisterClassEx(&wc)) {
        DWORD err = GetLastError();
        WCHAR buffer[100];
        swprintf(buffer, 99, L"Window Registration Failed!\nError code:%d", err);
        MessageBox(NULL, buffer, L"Error", MB_ICONEXCLAMATION | MB_OK);
        return false;
    }
    isRegistered = true;
    // Create window
    HWND hWnd = CreateWindowEx(
            WS_EX_LEFT, lpClassName,
            lpWindowName,
            WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME ^ WS_MAXIMIZEBOX,
            x,
            y,
            width,
            height,
            NULL,
            NULL,
            hInstance,
            NULL
    );
    if (hWnd == NULL) {
        MessageBox(NULL,
                   L"Window Creation Failed!",
                   L"Error",
                   MB_OK | MB_ICONEXCLAMATION);
        return false;
    }

    // Display window
    ShowWindow(hWnd, SW_SHOWDEFAULT);
    UpdateWindow(hWnd);

    SetForegroundWindow(hWnd);

    // Msg loop
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return true;
}

void register_add_window(HWND hWnd) {
    static bool isRegistered = false;

    LPCWSTR lpClassName = L"mWndAddClass";

    WNDCLASSEX wc = {
            sizeof(WNDCLASSEX),
            0x00,
            AddProc,
            0, 0,
            (HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
            LoadIcon(NULL, IDI_APPLICATION),
            LoadCursor(NULL, IDC_ARROW),
            (HBRUSH) (COLOR_WINDOW + 1),
            NULL,
            lpClassName,
            LoadIcon(NULL, IDI_APPLICATION)
    };
    if (!isRegistered && !RegisterClassEx(&wc)) {
        DWORD err = GetLastError();
        WCHAR buffer[100];
        swprintf(buffer, 99, L"Window Registration Failed!\nError code:%d", err);
        MessageBox(NULL, buffer, L"Error", MB_ICONEXCLAMATION | MB_OK);
    }

    isRegistered = true;

}

void register_note_window(HWND hWnd) {
    static bool isRegistered = false;

    LPCWSTR lpClassName = L"mWndNoteClass";

    WNDCLASSEX wc = {
            sizeof(WNDCLASSEX),
            0x00,
            NoteProc,
            0, 0,
            (HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
            LoadIcon(NULL, IDI_APPLICATION),
            LoadCursor(NULL, IDC_ARROW),
            (HBRUSH) (COLOR_WINDOW + 1),
            NULL,
            lpClassName,
            LoadIcon(NULL, IDI_APPLICATION)
    };
    if (!isRegistered && !RegisterClassEx(&wc)) {
        DWORD err = GetLastError();
        WCHAR buffer[100];
        swprintf(buffer, 99, L"Window Registration Failed!\nError code:%d", err);
        MessageBox(NULL, buffer, L"Error", MB_ICONEXCLAMATION | MB_OK);
    }

    isRegistered = true;

}